#include <csignal>
#include <iostream>
#include <unistd.h>
#include<signal.h>
#include<functional>
#include<vector>
#include<sys/types.h>


//混合使用操作block,pending,handler表的相关函数
//对于信号的位图结构OS为方便用户和OS交互操作，将信号集位图结构抽象成了一个名为sigset_t的结构体类型，来配合相关的函数操作信号集的信息
//下列OS提供的函数可以操作sigset_t类型的信号集位图，防止用户自己操作发生错误
// #include <signal.h>

// int sigemptyset(sigset_t *set);

// int sigfillset(sigset_t *set);

// int sigaddset(sigset_t *set, int signum);

// int sigdelset(sigset_t *set, int signum);

// int sigismember(const sigset_t *set, int signum);


void PrintPending(sigset_t &pending)
{
    std::cout << "current pending" << "[" << getpid() << "] : ";
    for(int signo = 31;signo > 0;signo--)
    {
        if(sigismember(&pending,signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    } 
    std::cout << std::endl;
}

int main()
{
    //1.阻塞（屏蔽）2号信号
    sigset_t block,oblock;
    //1.1清空信号集
    sigemptyset(&block);
    sigemptyset(&oblock);
    //1.2将2号信号添加进block
    sigaddset(&block,2);//本地栈中加入，并未加入内核
    sigprocmask(SIG_SETMASK,&block,&oblock);//加入内核

    //利用cnt展示pending表改变又恢复的场景
    signal(2,SIG_IGN);

    int cnt = 0;
    //2.发送2号信号，查看发送前后pending表的变化
    while(true)
    {
        sigset_t pending;
        //获取pending表并打印
        sigpending(&pending);

        PrintPending(pending);
        cnt++;
        sleep(1);

        if(cnt == 10)
        {
            sigprocmask(SIG_SETMASK,&oblock,nullptr);
        }
    }

    return 0;
}



































// //基于alarm实现理解OS运行

// using func_t = std::function<void()>;


// int gcount = 0;
// //OS任务集
// std::vector<func_t> gfuncs;

// // 把信号 更换 成为 硬件中断
// void hanlder(int signo)
// {
//     for(auto &f : gfuncs)
//     {
//         f();
//     }
//     std::cout << "gcount : " << gcount << std::endl;
//     //持续发送14号信号
//     alarm(1);
// }

// int main()
// {
//     gfuncs.push_back([](){
//         std::cout << "我是一个内核刷新操作" << std::endl; 
//     });

//     gfuncs.push_back([](){
//         std::cout << "我是一个检测进程时间片的操作，如果时间片到了，我会切换进程" << std::endl;
//     });

//     gfuncs.push_back([](){
//         std::cout << "我是一个内存管理操作，定期清理操作系统内部的内存碎片" << std::endl;
//     });

//     alarm(1);
//     signal(SIGALRM,hanlder);

//     while(true)
//     {
//         pause();
//         gcount++;
//         std::cout << "我醒来了..." << std::endl;
//     }

//     return 0;
// }


// void handler(int signum)
// {
//    std::cout << "我是: " << getpid() << ", 我获得了⼀个信号: " << signum << std::endl;
//    exit(0);
// }

// void Usage(char *argv[])
// {
//     std::cerr << "Usage: " << argv[0] << " -signumber pid" << std::endl;
// }

// int main(int argc,char *argv[])
// {
//     //函数调用系统调用
//     // //1.自主实现kill
//     // if(argc != 3)
//     // {
//     //     Usage(argv);
//     //     return 1;
//     // }

//     // int number = std::stoi(argv[1]+1); // 去掉-
//     // pid_t pid = std::stoi(argv[2]);
//     // int n = kill(pid, number);
//     // return n;

//     // //2.raise
//     // signal(2, handler); // 先对2号信号进⾏捕捉
//     // // 每隔1S，⾃⼰给⾃⼰发送2号信号
//     // while(true)
//     // {
//     //     sleep(1);
//     //     raise(2);
//     // }

//     // //3.abort
//     // signal(SIGABRT, handler);
//     // while(true)
//     // {
//     //     sleep(1);
//     //     abort();
//     // }

//     //键盘产生信号
//     // std::cout << "我是进程: " << getpid() << std::endl;

//     // // //ctrl+\
//     // // signal(SIGQUIT/*3*/, handler);
//     // // //ctrl + z
//     // // signal(SIGTSTP/*20*/, handler);
//     // while(true)
//     // {
//     //     std::cout << "I am a process, I am waiting signal!" << std::endl;
//     //     sleep(1);
//     // }


//     //信号处理
//     // ::signal(SIGINT,handler);
//     // // ::signal(SIGINT,SIG_IGN);
//     // // ::signal(SIGINT,SIG_DFL);
//     // while(true)
//     // {
//     //     std::cout << "I am a process, I am waiting signal!" << std::endl;
//     //     sleep(1);
//     // }
//     // while(true)
//     // {
//     //     std::cout << "I am a process, I am waiting signal!" << std::endl;
//     //     sleep(1);
//     // }
// }